perm filename PUPSFL.C[11,HE] blob sn#688209 filedate 1982-12-06 generic text, type T, neo UTF8
/* LINTLIBRARY */

/*
 * pupsetfilter.c
 *
 * Builds and sets a packet filter for a pup channel.
 *
 * Jeffrey Mogul @ Stanford	28-January-1981
 *
 */

#define offset(b,a) ( (int)&(b->a) - (int)(b) )

#include <puplib.h>
#include <pupconstants.h>
#include <pupstatus.h>
#include <puppacket.h>

pupsetfilter(Pchan,priority,Fpuptype,Fpupid,Fdstnet,Fdsthost,Fdstsock,
				Fsrcnet,Fsrchost,Fsrcsock)
struct PupChan *Pchan;		/* open pup channel */
uchar	priority;		/* filter priority */
uchar	*Fpuptype;		/* filter on pup type */
ulong	*Fpupid;		/* filter on pup id */
uchar	*Fdstnet;		/* filter on destination net */
uchar	*Fdsthost;		/* filter on destination host */
ulong	*Fdstsock;		/* filter on destination socket */
uchar	*Fsrcnet;		/* filter on source net */
uchar	*Fsrchost;		/* filter on source host */
ulong	*Fsrcsock;		/* filter on source socket */
{	/* */
	register struct enfilter *ef;	/* used as a temporary */
	register struct PupPacket *pp;	/* used as a placeholder */
	register struct EnPacket *ep;	/* used as a placeholder */
	int	efterms;	/* terms in the filter */

	/*
	 * Here we would switch on Pchan->transport to
	 * decide what sort of filter mechanism to build;
	 * currently, the only choice is an enfilter.
	 */
	
	ef = &(Pchan->filter.en);	/* get address of filter */

	efinit(ef,priority);	/* init the filter with the given priority */

	/* always insure that the ethernet packet type is Pup */

	efwdinsert(ef,offset(ep,PacketType),PUP);
	efterms = 1;	/* always one term, at least */

	/* now, conditionally insert each optional test */
	/* !!!!! TO AVOID OVERFLOW, BUNCH HOST/NET IF BOTH GIVEN!!!! */

	if (Fpuptype) {
		efchinsert(ef,ENPACKOVER+offset(pp,PupType),*Fpuptype);
		efterms++;
		}
	if (Fpupid) {
		eflginsert(ef,ENPACKOVER+offset(pp,PupID),makelong(*Fpupid));
		efterms++;
		}
	if (Fdstnet) {
		efchinsert(ef,ENPACKOVER+offset(pp,PupDst.pk_Net),*Fdstnet);
		efterms++;
		}
	if (Fdsthost) {
		efchinsert(ef,ENPACKOVER+offset(pp,PupDst.pk_Host),*Fdsthost);
		efterms++;
		}
	if (Fdstsock) {
		eflginsert(ef,ENPACKOVER+offset(pp,PupDst.pk_FSocket),
				makelong(*Fdstsock));
		efterms++;
		}
	if (Fsrcnet) {
		efchinsert(ef,ENPACKOVER+offset(pp,PupSrc.pk_Net),*Fsrcnet);
		efterms++;
		}
	if (Fsrchost) {
		efchinsert(ef,ENPACKOVER+offset(pp,PupSrc.pk_Host),*Fsrchost);
		efterms++;
		}
	if (Fsrcsock) {
		eflginsert(ef,ENPACKOVER+offset(pp,PupSrc.pk_FSocket),
				makelong(*Fsrcsock));
		efterms++;
		}

	/*
	 * between each term in the filter, include an AND operation.
	 * i.e., for n terms, n-1 ANDs.
	 */
	for (; efterms > 1 ; efterms--) {
		if (efAND(ef) != OK) return(FILTERTOOBIG);
		}

	/* filter is built, insure that it is set onto channel */
	ensetfilt(Pchan->ifid, &Pchan->filter.en);

	return(OK);
}